package com.netx.cubigraf.entities;
import com.netx.generics.sql.Table;
import com.netx.generics.time.Date;
import com.netx.generics.time.Moment;
import com.netx.data.Connection;
import com.netx.data.DatabaseException;
import com.netx.data.Entity;
import com.netx.data.ValueList;


public class Facturas extends Entity {

	public Facturas() {
		super();
	}
	
	// for Servicos:
	// (assumes a transaction has been started)
	void adicionarLinha(long cdgServico, long cdgCliente, double preco) throws DatabaseException {
		// encontrar a factura certa para inserir:
		Date base = new Moment().getDate();
		base.setDay(base.getDay()<16 ? 1 : 16);
		
		long cdgFactura = 0;
		Table result = select("cdg_factura", "cdg_cliente="+cdgCliente+" AND estado='a' AND data_criacao='"+base.format(getConnection().getDatabase().getDriver().getDateFormat())+"'");
		if(result.isEmpty()) {
			// criar factura:
			ValueList values = new ValueList();
			values.addValue("cdg_cliente", cdgCliente);
			values.addValue("estado", "a");
			values.addValue("data_criacao", base);
			cdgFactura = insert(values);
		}
		else {
			cdgFactura = result.getLong(1, 0);
		}
		
		// inserir a linha:
		ValueList values = new ValueList();
		values.addValue("preco", preco);
		values.addValue("data_aprecado", new Moment().getDate());
		values.addValue("passado", false);
		insertRelation(cdgFactura, cdgServico, values);
	}

	// for Servicos:
	// (assumes a transaction has been started)
	boolean existeLinha(long cdgServico) throws DatabaseException {
		return !getConnection().select("cdg_factura FROM linhas_factura WHERE cdg_servico="+cdgServico).isEmpty();
	}

	// for Servicos:
	// (assumes a transaction has been started)
	void removerLinha(long cdgServico) throws DatabaseException {
		// remover a linha:
		long cdgFactura = getConnection().select("cdg_factura FROM linhas_factura WHERE cdg_servico="+cdgServico).getLong(1, 0);
		deleteRelation(cdgFactura, cdgServico);
		// remover a factura, se vazia:
		Table result = getConnection().select("cdg_servico FROM linhas_factura WHERE cdg_factura="+cdgFactura);
		if(result.isEmpty()) {
			delete(cdgFactura);
		}
	}

	public Table verFacturasAbertas() throws DatabaseException {
		return getConnection().select("facturas.cdg_factura, facturas.data_criacao, clientes.nome FROM facturas, clientes WHERE facturas.cdg_cliente=clientes.cdg_cliente AND facturas.estado='a' ORDER BY facturas.data_criacao, clientes.nome");
	}
	
	public int contaLinhasAPassar(long codigoFactura) throws DatabaseException {
		return getConnection().select("count(cdg_factura) FROM linhas_factura WHERE cdg_factura="+codigoFactura+" AND passado=0").getInt(1, 0);
	}

	public Table[] verFacturaParaPassar(long codigoFactura) throws DatabaseException {
		Connection c = getConnection();
		Table factura = c.select("facturas.data_criacao, clientes.nome_completo, clientes.cdg_infologia FROM facturas, clientes WHERE facturas.cdg_factura="+codigoFactura+" AND facturas.cdg_cliente=clientes.cdg_cliente");
		Table linhas_factura = c.select("servicos.cdg_servico, servicos.referencia, servicos.data_abertura, servicos.nome, servicos.numero_cores, linhas_factura.preco FROM servicos, linhas_factura WHERE linhas_factura.cdg_factura="+codigoFactura+" AND linhas_factura.cdg_servico=servicos.cdg_servico AND linhas_factura.passado=0 ORDER BY servicos.referencia");
		return new Table[] {factura, linhas_factura};
	}
	
	// Factura:
	// 1. numero
	// 2. nome do cliente
	// Linha (servicos):
	// 1. referencia
	// 2. data de abertura
	// 3. nome
	// 4. numero de cores
	// 5. largura
	// 6. altura
	// 7. preco
	public Table[] verFactura(long codigoFactura) throws DatabaseException {
		Connection c = getConnection();
		Table factura = c.select("f.numero, c.nome_completo FROM facturas f, clientes c WHERE f.cdg_factura="+codigoFactura+" AND f.cdg_cliente=c.cdg_cliente");
		Table linhas_factura = c.select("s.referencia, s.data_abertura, s.nome, s.numero_cores, s.largura, s.altura, lf.preco FROM servicos s, linhas_factura lf WHERE lf.cdg_factura="+codigoFactura+" AND lf.cdg_servico=s.cdg_servico ORDER BY s.referencia");
		return new Table[] {factura, linhas_factura};
	}
	
	public void passarFacturas(long codigoFactura) throws DatabaseException {
		Connection c = getConnection();
		synchronized(c) {
			startTransaction();
			_passar(codigoFactura);
			commit();
		}
	}

	public void emitirFactura(long codigoFactura, int numeroFactura) throws DatabaseException {
		Connection c = getConnection();
		synchronized(c) {
			startTransaction();
			ValueList values = new ValueList();
			values.addValue("estado", "e");
			values.addValue("numero", numeroFactura);
			update(codigoFactura, values);
			_passar(codigoFactura);
			commit();
		}
	}
	
	// assumes a transaction has been started:
	private void _passar(long codigoFactura) throws DatabaseException {
		Connection c = getConnection();
		Servicos servicos = (Servicos)c.getEntity("servicos");
		Table result = c.select("cdg_servico FROM linhas_factura WHERE linhas_factura.cdg_factura="+codigoFactura+" AND linhas_factura.passado=0");
		ValueList values = new ValueList();
		values.addValue("passado", true);
		for(int i=0; i<result.getRowCount(); i++) {
			updateRelation(codigoFactura, result.getLong(1, i), values);
			//TODO sera necessario este estado?
			servicos.facturarServico(result.getLong(1, i));
		}
	}
}
